﻿using QuickFill.Models;
using QuickFill.Services;
using Microsoft.Win32;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;

namespace QuickFill.ViewModels
{
    public class MainViewModel : INotifyPropertyChanged
    {
        private readonly DocumentService _docService;
        private readonly ExcelService _excelService;
        private readonly MergeService _mergeService;

        // 进度报告
        private ProgressReport _progress;

        public ObservableCollection<TemplateFile> TemplateFiles { get; } = new();
        public ICommand SelectTemplatesCommand { get; }
        public ICommand RemoveTemplatesCommand { get; }
        public ICommand SelectExcelCommand { get; }
        public ICommand ExecuteMergeCommand { get; }
        public ICommand CancelCommand { get; }
        public ICommand ExitCommand { get; }
        public ICommand OpenOutputCommand { get; }

        public string ExcelPath
        {
            get => _progress.ExcelPath;
            set
            {
                if (_progress.ExcelPath != value)
                {
                    _progress.ExcelPath = value;
                    OnPropertyChanged(nameof(ExcelPath));
                }
            }
        }

        public int ProgressPercentage
        {
            get => _progress.Percentage;
            set
            {
                if (_progress.Percentage != value)
                {
                    _progress.Percentage = value;
                    OnPropertyChanged(nameof(ProgressPercentage));
                }
            }
        }

        public string ProgressMessage
        {
            get => _progress.Message;
            set
            {
                if (_progress.Message != value)
                {
                    _progress.Message = value;
                    OnPropertyChanged(nameof(ProgressMessage));
                }
            }
        }

        public bool IsProcessing
        {
            get => _progress.IsProcessing;
            set
            {
                if (_progress.IsProcessing != value)
                {
                    _progress.IsProcessing = value;
                    OnPropertyChanged(nameof(IsProcessing));
                    OnPropertyChanged(nameof(IsNotProcessing));
                }
            }
        }

        public bool IsNotProcessing => !IsProcessing;

        private CancellationTokenSource _cancellationTokenSource;

        public MainViewModel()
        {
            _docService = new DocumentService();
            _excelService = new ExcelService();
            _mergeService = new MergeService();
            _progress = new ProgressReport();

            SelectTemplatesCommand = new RelayCommand(_ => SelectTemplateFiles());
            RemoveTemplatesCommand = new RelayCommand(RemoveSelectedTemplates);
            SelectExcelCommand = new RelayCommand(_ => SelectExcelFile());
            ExecuteMergeCommand = new AsyncRelayCommand(ExecuteMergeAsync, CanExecuteMerge);
            CancelCommand = new RelayCommand(_ => CancelProcessing());
            ExitCommand = new RelayCommand(_ => Application.Current.Shutdown());
            OpenOutputCommand = new RelayCommand(_ => OpenOutputDirectory());
        }

        private void SelectTemplateFiles()
        {
            var openFileDialog = new OpenFileDialog
            {
                Filter = "Word 文档|*.doc;*.docx",
                Multiselect = true
            };

            if (openFileDialog.ShowDialog() == true)
            {
                foreach (var fileName in openFileDialog.FileNames)
                {
                    if (!TemplateFiles.Any(f => f.Path == fileName))
                    {
                        TemplateFiles.Add(new TemplateFile(fileName));
                    }
                }
            }
        }

        private void RemoveSelectedTemplates(object obj)
        {
            if (obj is IList selectedItems)
            {
                var itemsToRemove = selectedItems.Cast<TemplateFile>().ToList();
                foreach (var item in itemsToRemove)
                {
                    TemplateFiles.Remove(item);
                }
            }
        }

        private void SelectExcelFile()
        {
            var openFileDialog = new OpenFileDialog
            {
                Filter = "Excel 文件|*.xlsx;*.xls"
            };

            if (openFileDialog.ShowDialog() == true)
            {
                ExcelPath = openFileDialog.FileName;
            }
        }

        private bool CanExecuteMerge(object parameter) => !IsProcessing;

        private async Task ExecuteMergeAsync(object parameter)
        {
            if (!ValidateInputs()) return;

            _cancellationTokenSource = new CancellationTokenSource();
            var cancellationToken = _cancellationTokenSource.Token;

            try
            {
                IsProcessing = true;
                ProgressMessage = "正在读取Excel数据...";
                ProgressPercentage = 0;

                // 读取Excel数据
                var data = await Task.Run(() => _excelService.ReadExcelData(ExcelPath));

                ProgressMessage = $"找到 {data.Count} 条数据记录";
                await Task.Delay(500);

                ProgressMessage = "开始处理文档...";

                int totalFiles = TemplateFiles.Count * data.Count;
                int processed = 0;

                // 获取当前程序所在目录
                string appDirectory = AppDomain.CurrentDomain.BaseDirectory;
                string outputBaseDir = Path.Combine(appDirectory, "output");

                // 处理每个模板文件
                foreach (var template in TemplateFiles)
                {
                    // 处理每条数据记录
                    foreach (var record in data)
                    {
                        // 检查取消请求
                        if (cancellationToken.IsCancellationRequested)
                        {
                            ProgressMessage = "操作已取消";
                            return;
                        }

                        // 获取文件夹名称
                        string folderName = record["FolderName"].ToString();
                        string outputFolder = Path.Combine(outputBaseDir, folderName);
                        Directory.CreateDirectory(outputFolder); // 确保文件夹存在

                        // 构造输出文件名（保留原始文件名）
                        string fileName = Path.GetFileName(template.Path);
                        string outputPath = Path.Combine(outputFolder, fileName);

                        // 如果文件已存在，添加序号避免覆盖
                        int count = 1;
                        while (File.Exists(outputPath))
                        {
                            string newFileName = $"{Path.GetFileNameWithoutExtension(fileName)}_{count}{Path.GetExtension(fileName)}";
                            outputPath = Path.Combine(outputFolder, newFileName);
                            count++;
                        }

                        // 执行邮件合并
                        await Task.Run(() =>
                        {
                            _mergeService.MergeDocument(template.Path, outputPath, record);
                        });

                        // 更新进度
                        processed++;
                        ProgressPercentage = (int)((double)processed / totalFiles * 100);
                        ProgressMessage = $"正在处理: {processed}/{totalFiles} - {Path.GetFileName(outputPath)}";
                    }
                }

                ProgressMessage = "处理完成!";
                MessageBox.Show($"成功处理 {totalFiles} 个文档!", "完成",
                    MessageBoxButton.OK, MessageBoxImage.Information);
            }
            catch (OperationCanceledException)
            {
                ProgressMessage = "操作已取消";
            }
            catch (Exception ex)
            {
                MessageBox.Show($"处理过程中出错: {ex.Message}", "错误",
                    MessageBoxButton.OK, MessageBoxImage.Error);
                ProgressMessage = "处理失败";
            }
            finally
            {
                IsProcessing = false;
                _cancellationTokenSource = null;
            }
        }

        private void CancelProcessing()
        {
            _cancellationTokenSource?.Cancel();
        }

        private bool ValidateInputs()
        {
            if (TemplateFiles.Count == 0)
            {
                MessageBox.Show("请至少选择一个Word模板文档", "提示",
                    MessageBoxButton.OK, MessageBoxImage.Warning);
                return false;
            }

            if (string.IsNullOrWhiteSpace(ExcelPath))
            {
                MessageBox.Show("请选择Excel数据源文件", "提示",
                    MessageBoxButton.OK, MessageBoxImage.Warning);
                return false;
            }

            if (!File.Exists(ExcelPath))
            {
                MessageBox.Show("Excel文件不存在或已被移动", "错误",
                    MessageBoxButton.OK, MessageBoxImage.Error);
                return false;
            }

            return true;
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        // 实现打开输出目录方法
        private void OpenOutputDirectory()
        {
            try
            {
                string outputDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "output");
                if (Directory.Exists(outputDir))
                {
                    Process.Start("explorer.exe", outputDir);
                }
                else
                {
                    MessageBox.Show("输出目录尚未创建，请先执行填写操作", "提示",
                        MessageBoxButton.OK, MessageBoxImage.Information);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"无法打开输出目录: {ex.Message}", "错误",
                    MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
    }

    public class ProgressReport : INotifyPropertyChanged
    {
        private string _excelPath;
        private int _percentage;
        private string _message = "准备就绪";
        private bool _isProcessing;

        public string ExcelPath
        {
            get => _excelPath;
            set
            {
                if (_excelPath != value)
                {
                    _excelPath = value;
                    OnPropertyChanged(nameof(ExcelPath));
                }
            }
        }

        public int Percentage
        {
            get => _percentage;
            set
            {
                if (_percentage != value)
                {
                    _percentage = value;
                    OnPropertyChanged(nameof(Percentage));
                }
            }
        }

        public string Message
        {
            get => _message;
            set
            {
                if (_message != value)
                {
                    _message = value;
                    OnPropertyChanged(nameof(Message));
                }
            }
        }

        public bool IsProcessing
        {
            get => _isProcessing;
            set
            {
                if (_isProcessing != value)
                {
                    _isProcessing = value;
                    OnPropertyChanged(nameof(IsProcessing));
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public class RelayCommand : ICommand
    {
        private readonly Action<object> _execute;
        private readonly Predicate<object> _canExecute;

        public RelayCommand(Action<object> execute, Predicate<object> canExecute = null)
        {
            _execute = execute ?? throw new ArgumentNullException(nameof(execute));
            _canExecute = canExecute;
        }

        public bool CanExecute(object parameter) => _canExecute?.Invoke(parameter) ?? true;

        public void Execute(object parameter) => _execute(parameter);

        public event EventHandler CanExecuteChanged
        {
            add => CommandManager.RequerySuggested += value;
            remove => CommandManager.RequerySuggested -= value;
        }
    }

    public class AsyncRelayCommand : ICommand
    {
        private readonly Func<object, Task> _execute;
        private readonly Predicate<object> _canExecute;
        private bool _isExecuting;

        public AsyncRelayCommand(Func<object, Task> execute, Predicate<object> canExecute = null)
        {
            _execute = execute ?? throw new ArgumentNullException(nameof(execute));
            _canExecute = canExecute;
        }

        public bool CanExecute(object parameter)
        {
            return !_isExecuting && (_canExecute?.Invoke(parameter) ?? true);
        }

        public async void Execute(object parameter)
        {
            _isExecuting = true;
            RaiseCanExecuteChanged();

            try
            {
                await _execute(parameter);
            }
            finally
            {
                _isExecuting = false;
                RaiseCanExecuteChanged();
            }
        }

        public event EventHandler CanExecuteChanged;
        public void RaiseCanExecuteChanged()
        {
            CanExecuteChanged?.Invoke(this, EventArgs.Empty);
        }
    }
}